F = GF(2^255-19)
dM = F(-121665)
d = F(-121665/121666)
ii = sqrt(F(-1))
def lobit(x): return int(x) & 1
def hibit(x): return lobit(2*x)

magic = sqrt(dM-1)
if lobit(magic): magic = -magic

def eddsa_decode(y_ser):
    """
    Recover x,y corresponding to the eddsa standard representation.
    """
    hi = int(y_ser) & 2^255
    y = F(y_ser-hi)
    
    x = sqrt((y^2-1)/(d*y^2+1))                                                               
    if int(x) & 1: x = -x
    if hi: x = -x                                                                    
    assert y^2 - x^2 == 1+d*x^2*y^2
    return (x,y)

def eddsa_to_decaf(x,y):
    """
    Converts an EdDSA point to a Decaf representation, in a manner compatible
    with libdecaf.
    
    The input point must be even.
    
    Note well!  Decaf does not represent the cofactor information of a point.
    So e2d(d2e(s)) = s, but d2e(e2d(x,y)) might not be (x,y).
    """
    if x*y == 0: return 0 # This will happen anyway with straightforward square root trick
    if not is_square((1-y)/(1+y)): raise Exception("Unimplemented: odd point in eddsa_to_decaf")
    if hibit(magic/(x*y)): (x,y) = (ii*y,ii*x)
    if hibit(2*magic/x): y = -y
    s = sqrt((1-y)/(1+y))
    if hibit(s): s = -s
    return s

def isqrt_trick(to_isr,to_inv):
    """
    The "inverse square root" trick:
    Return 1/sqrt(to_isr), 1/to_inv.
    Also return their product because that turns out to be useful.
    """
    to_sqrt = to_isr*to_inv^2
    
    if to_sqrt == 0: return 0,0,0 # This happens automatically in C; just to avoid problems in SAGE
    if not is_square(to_sqrt): raise Exception("Not square in isqrt_trick!")
    
    isr_times_inv = 1/sqrt(to_sqrt)
    isr = isr_times_inv * to_inv
    inv = isr_times_inv * isr * to_isr
    
    assert isr^2 == 1/to_isr
    assert inv == 1/to_inv
    return isr, inv, isr_times_inv
    

def eddsa_to_decaf_opt(x,y,z=None):
    """
    Optimized version of eddsa_to_decaf.   Uses only one isqrt.
    There's probably some way to further optimize if you have a T-coord,
    but whatever.
    """
    if z is None:
        # Pretend that we're in projective coordinates
        z = F.random_element()
        x *= z
        y *= z
    
    isr,inv,isr_times_inv = isqrt_trick(z^2-y^2,x*y)
    minv = inv*magic*z
    
    rotate = hibit(minv*z)
    if rotate:
        isr = isr_times_inv*(z^2-y^2)*magic
        y = ii*x
    
    if hibit(2*minv*y) != rotate: y = -y
    s = (z-y) * isr
    
    if hibit(s): s = -s
    return s


def decaf_to_eddsa(s):
    """
    Convert a Decaf representation to an EdDSA point, in a manner compatible
    with libdecaf.
    
    Note well!  Decaf does not represent the cofactor information of a point.
    So e2d(d2e(s)) = s, but d2e(e2d(x,y)) might not be (x,y).
    """
    if s == 0: return (0,1)
    if s < 0 or s >= F.modulus(): raise Exception("out of field!")
    s = F(s)
    if hibit(s): raise Exception("invalid: s has high bit")
    if not is_square(s^4 + (2-4*dM)*s^2 + 1): raise Exception("invalid: not on curve")
    
    t = sqrt(s^4 + (2-4*dM)*s^2 + 1)/s
    if hibit(t): t = -t
    y = (1-s^2)/(1+s^2)
    x = 2*magic/t
    
    if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit")
    
    assert y^2 - x^2 == 1+d*x^2*y^2
    return (x,y)

def decaf_to_eddsa_opt(s):
    """
    Convert a Decaf representation to an EdDSA point, in a manner compatible
    with libdecaf.  Optimized to use only one invsqrt.
    
    This function would be slightly simpler if we didn't want to decode to affine.
    """
    if s < 0 or s >= F.modulus(): raise Exception("out of field!")
    s = F(s)
    if hibit(s): raise Exception("Invalid: s has high bit")
    if s == 0: return (0,1)
    
    curve_eqn = s^4 + (2-4*dM)*s^2 + 1
    isr,inv,isr_times_inv = isqrt_trick(curve_eqn,s*(1-s^2)*(1+s^2))
    if isr == 0: raise Exception("Invalid: nonstandard encoding of zero")
    
    x = 2 * magic * s * isr
    y = (1-s^2)^2 * s * inv
    
    tmp = isr_times_inv * curve_eqn * (1+s^2) # = sqrt(curve_eqn) / s / (1-s^2)
    hibit_t = hibit(tmp * (1-s^2))
    if hibit_t: x = -x
    if lobit(tmp * (1+s^2)) != hibit_t: raise Exception("invalid: bits don't match")
    
    assert y^2 - x^2 == 1+d*x^2*y^2
    return (x,y)

# Tests, but they require some pregenerated points
points = [
(0x2cafede3353135c821d79fa40e25cf3699be47f926ab6e53d0e0adfd014f19a0,0x70d0fdefa7d4b83d5a56347b1489aaaaa13c91c711f533e91ec3e420e731fd98),
(0x28471815cf3c4d9b8dcd7684dcdd676cb3117c5255b03f32238356a4acae433f,0x306740203a6d0b4d414b19b907967c3c7ccb5c68bb30c39addd914c47284dfeb),
(0x2c0c4eb0ae23d2728b13e9af3ab5b4ba6a4727dcf2cd6b269847e36ba91dbe45,0x7789d470a4b21a14ded681de924eaf4af17833197a0c9dedd223b6588e529e1b),
(0x0a9a0497e538bc1856892cc61b859dea42156fcdc62b66e1cc341c7a6d44affb,0x3bc531dcd67c252f0d4578ce80f06650339d5a6a7bac6fb220d994d8cff03c67),
(0x040876b83d9a59788d5a8b308e1c74255603d603353c0748dea9e46e6297f460,0x44caffd4eb82c01ea9ab40875f951c3a86605535d25a3ca40b09dfa47c3f0079),
(0x08e2924ad3c0a7b1e1a8095d7105d152eb3734e9b046153946a6e1ffb81ee042,0x4831ef0a61c4f14cb88a4f05dd05206c21734ece774fcabb10ccdffbf68e4d31),
(0x105d54f7395076044be05e2a1f92b5d35aa309bd3b51ffa13930c79aea9086a0,0x5d8f2bf40b593f40fec4bcd1937e2e3c42221ab5a53fb9ccd6f7b40361f500f5),
(0x0607a3605a63a801ecbc78f0c662891b13c32eb088e4010509520f341ff405ab,0x1fb01b611b929b0ae76d5d9fcb3230eae78e4a5b883bf063ac8294e7faa0a1ac),
(0x25a6dbb50f51e49cd2f1ca4ef2f611a0f2bbee5fde9bb16ab2bd2fd544524d08,0x3723a079cd53bb0f66900c9520c482783ede56c04577cfa1b7ec180eaeb96535),
(0x21ace5501adc79b894479c8b1859975daf5896e5cee056d3f36d3604df414151,0x1581fc4e7ba5815300e7d4229b0a33b3270f9c14ba00a272cdf657ed4ab40147),
(0x2afd4db18777a9d4be03613982984496c8d2ebd6437611381e275e1b1a489356,0x7714135c85cfc9980523d6da7eeecee940240e8060be8261bbde607d229beb5c),
(0x2c55dcc8fa715d32fcf51bce0f0a31e44c3f670fedb77b11ae1fbcc7266a95d0,0x274c10042bf6d54c20631ddf5ac118d0f27db35b9f471643e309564cf0406ac9),
(0x3771e9a7f4176a9e0c86d6794985ea7a21377d0c3e07160135ef0bbd33193c88,0x5c053b543c6410dc46c9beaca721332f618ea6f8ee612e7a01c90f492d34884d),
(0x12a902fe4628586de88003082c8b409049f403d9d8467251967eb01a8d0d46bc,0x57126efc10bab3b42919389f5adabe3852612d4f5431380172e114f5e3f9478e),
(0x1925479ebacce955c4c6ca85236702201b28b7acbee64aa7e13b263af156d5f7,0x1012c8da84330dd7e57599d7230a798ad8d782e53951002d8ce2d6dd61ad22ab),
(0x3fb563cb76965388d2b7cd310e8883168a44b54f51e87e85450d8082cda27c32,0x5cc8f5a6d9c932f3c5bb73d8aaad712be8a612f3afafa968dfdfe4bf89de9cec),
(0x39a7f4702b154a76a412f600a07faec89a08aebea657c60b95009ba7459ef89f,0x600c2f535231b50626e8f82c941c65083aa2b7f0b05abe837a3f8a561eb4c111),
(0x04bb82dbce90079b8e900971137cc6b250361e904e2dd3f493d5de030a64da18,0x3131af645b0328fbc1ba1041940f792892f330801ae4cbae720d0eed272852ea),
(0x33816ae7bcdd2e844fd2317e6ed2b7a9064ade4c550c34683107550a102a5844,0x1f75ef4620c6b9fc1df0550cebe7e77a312d52ebcec44531fc8fd579cd73a6f7),
(0x243612efda2f2520e619461d64e56650f5a2926d6d0e7e0f5fb2bde0bc5bdd02,0x19bab77d15fbc92056f85d17e47ae57530aacc3ebf17209772aba8cf221aadbf),
(0x2440bf712fdeef73e6d55c6ea69a61596df81419d1921882d1f09d7f0fc21e7c,0x1d3ceb3cc153bd08590cb470dde69dbb9abae762f5fabf30079d9aa188072575),
(0x015c63020852ff73044ecea7037602ee6f9fede01a7ce27489bad570d6946dbf,0x4ec777e530371db59c116842447e2289ab66a1291c99b195d2665b6fc8254988),
(0x0412cb12cc650ab9d7a78e98c02a254d2efb27525850c362c7e25f7a140aa261,0x499d7f57650ecd1fe14ca5091a891f6706eec2323f479fdd3608305e24a5474d),
(0x03bfd7b5ce73d5e328aa268828228ef133bd656a13f6bf5a85c42f7b81c98b3c,0x22f309299d1bbf9f9e0d7005d6bb9e3c9063bafa5460e3910f4f11dc333daea2),
(0x047e543079617fca27a7128d03935f4c2ef763dcf12fdf56435c7a637d6c3e94,0x0c478ede8b604da9a9916fdd90da33cf2a7fe7a41b4649e22daab5010b0e414c),
(0x04952979f1593cdb8789d50749d4293113b6d9ea0cc883dbab06254d9ffac408,0x365d7e1057f73d720e4a0be812fce840a5e2f26364a056b5449c2680d834567c),
(0x17668b514606ff6272cf0c2d5ab0be82556ac53ce7158dc6dcd0b1b197063ebf,0x0bf36715a34fcadaf9b14d7ace129042cb0b2d93d3b8832bc7e44c801cb0c0b2),
(0x064bd96210b06010d3aa5a3b60630634bbc398c03fe13c6d3ac06590604eec28,0x60496e9d6d158e82b5e4436eb250be5ac907b619f8a53eb9f615b80462d05a7e),
(0x16c94534e51a349a2578283ef836c966fee6d76a9402c2dfb1797817c553e7ad,0x5cd65e6ea0651537d545ea9d2aaf7a0ab3d75e85b807aafb353b92e8782165d7),
(0x3a2f74ac2e759c2a84c8a15ccd8a330e4cbbcdd4f0f78f8c05a18b5e5237cb57,0x19571437d279b1be994a05bc4de7a24f664eea8960ba8128eb15be6ed6bc78b3),
(0x15e1c51b351ca71c5d6fa8aa91a568d61821df00c97672540d21169dcbb39ec7,0x6806c3d0918d189ac2d744fa2ebe968d397b4b3028978af910b91ce1d10d9430),
(0x1dd8871f80931ec7d408dd7f1c45d056429d8b975f0fd1b3e5b17be43380f360,0x48d984bc9b5e16fa12274cab9b3fdeb5753eb9d2195e1edde15710b1ff4a78b7),
(0x013dfd1f90e3df0b9ab3bc0a15955b4df218798cf65e50123167570d7e7d5435,0x373878bbd07997f352534a4e237d6cabdcdfc38a558b1e6c4f02cdd495a99a1d),
(0x3b191f28f07028b2d4737ee9c9a8b38b9cb1546fa69dbc1f889d36476f7970ae,0x13dc6f5094bc37892298d4b25d37b7241f443f49011cf89fa93a2a7c83639405),
(0x04013f892451bfae60cc2016f4488f8557a476c4fba67a37bbb7755ea6421229,0x4e7c1ffb43a208f6c63a1599477f4912b23ff764c096d58ef6121dbc5260edb9),
(0x3df16cb8ba0d99c2a83623080968e0a0e737b9791db5518b33f774c1b1ca1066,0x106d22b8426ea5d6c02790ffc8499bcb4fff4ace5815b52e59198fda1522d22b),
(0x126a70cdd2ea42fad54cdad0bbc6d43b4035e8796608b8a71fca7a64b4c866b5,0x35b20471c614035813ecb721ab724c9936670be4dd9083af30c565859afb451d),
(0x27003d61ae8bae9abe323a2417326fc9605373842133569e68db07766fdf13b4,0x5134cfa6c9092ca7b70c97a2cd4f2f920a3d3f84a813479c001599ec6e0a762c),
(0x35d0a38a36d9a0f9f86d5e57ae4476a21a66c15b38dc69ede62a0e7aa19177e0,0x4827367a0fbbbf849d1728d247d75ba027afa74278ee781c521b9bd2387622b7),
(0x20f482e14c42db88844c1aeae82c8e5223508232b1f17f23da39c3ef728e0a01,0x519b487006b05dd35de8457092fe3ed666591f4ebe1cffcf699198ef28f0bac1),
(0x0455543fbe2bb34477f589423af9e780a09b5bdc70a8e7c9e883391177ce3a41,0x4f7954a5999c33ee181676b0f94060bbcf9d9fe5c6ba8bf88da84b1de02a3371),
(0x3dfc6e4032693471f402fb3b20ae6ff0cac0dcb6335e4791b9afec311c489de1,0x05821acf4d3968aad6978fd5790edb5f5df303190ec2811aab0954e5ec178427),
(0x196f7fdf033a6057bc85bab561eb75bb7c1fbdfe01dd4647c53faa18acb55552,0x2e0290811c4c96b696e5a4f4f51f44e9281933759926e993e32d7a5a203a83c9),
(0x1e1b753c869f8f455e9ca31cac2b9750ed0db980b64899bfbf6ed4057a9d18ef,0x661eb553df91b11ee336b0cd803a62b3cd5096b9b7ffe7df5447fd17c6eead95),
(0x0fffada295bda0429748932b87cbdef25c25dcd600764a0ca7a523175ee1aaf8,0x2260e201c9447f7f5fc96dbf94ecfd84025e32bdb6527e5f6ea7b491ec0868ac),
(0x01207be02e598e827d104537a9f6374e05db179868bc5d1f5b4465327af53144,0x7f9e45d36a1a06cbe82c4a5b158a5c8d4052a4ce3b243c97d732f4f96d51ad69),
(0x2abd34573b48783a1de5f46331a812251a044a541b4b22cd9c5511b4970cc7e9,0x16f9615d8cfe906b7d011dd3028c8c1259d3197263d4f2c8104c1047c70cd1b5),
(0x0eedecfb37efd92ac7521f6671a93e9254d7bc14a1a983c88b9b87988af470e7,0x74ce5bac7f261a5defc289d7821e7919b640b96d37db5e2286c2bf2511286d71),
(0x260a03d8414634a8b6369a20aca5a3e2eebe47cff1e00a5b15c1041af0101402,0x3d17189e0f1de4c53e0415c6e7d7e4fd947ade06ab462ccce78c9947d6d8a32c),
(0x2884875ff2049d26104a2d850e93bb553dc11580374f9662cda1291b91fbc7be,0x362c024afc7e10fc16fc10e3390851ce1639cf40dffa8e40ff1e6f564093d075),
(0x03e7b8bc5eda3558c334fc7425dd008828f34fdc7df6e61f275d941cedd9f51b,0x10bb3cdb00abe58aaa55dbbf14666f2f837443f65f104b56c80c0aa20e8f7045),
(0x0c41e8d17434987c3fe1f83ca28c4c7a29275477c1829e33d272e3c8634c6ccf,0x48078d11dee44befe72a119cd3fba0cec3f2807f1c585d52f39d46cf63691236),
(0x3f0559e744ece5cf0f556a91f747f574946f2d305a61e6d4ad0699d056fcacca,0x6a28ebe3a77282e19b91b30b9ff316dc84f4bc84de5146b2f0dc0a4043a2c26c),
(0x041304aefe8d8e19d8c301a40e633268eaaca71679cb928eb3144707d830eec1,0x565323812efe5aa85d62ae86ef0094f096fd3cd02fe0fde621dcac47932b9cd5),
(0x2a17f7f61f2704e03a14ba008c3159ff0d1ef4733fe1f5f2b2b90e452976bc8b,0x26bab8aa41bdf0f45350b6185389d50417a95a3b951cc1a5095fd9ed2c8c9bb3),
(0x04bc19c92dc1b8fc6fb66631c2e7134dde56a9f185680e3ceaa438e2a2cfb2ec,0x304318c6b602176cd8920fe37da7a62ab71084a2cd4f6a529fc6d5fa2bed7761),
(0x0004962f43c64c0a1f25e03666b017af771050417f5eda0ad217cf3659e8854f,0x7a8f0501d26438df711067b0ae3131351c44905d5ba5c0c21da21c455f127b50),
(0x3f4cd4a37036d932dab0234139707d3176c77c692f8c1a12e114526f4b1e903a,0x49e8ec31649d4d0c13c18bc39c205f89bce5469c1b9ba435c5e32dc6c60c2412),
(0x3fea5f5dd191dab2222ddb15ad45ad96db58326f453dcc179cba27e71e169e3e,0x67b4e3c3834e8a8ece8f7e9abe535deb51155d276acf30e0d79832115b35814d),
(0x0744e0bbd51d38f635827f8dda3d019e61a0337c274cfa3aa040971aeafea861,0x4d14417bed8e4bb606f83676b3fb11dc95622d2788825a8a92addf381b062ac7),
(0x2ef66265e7e66ac9fbaa225c1ddc30a5f4d14c50bc04f1f7b5a4f9431fc5f3b0,0x741d4d2574942720802252deb7f0a0db2d12d2ea8baa4e70e72d4c202940870d),
(0x316d162ecfa06096e1d42664e627d41954bee5aede57959a88fec86872f1633b,0x589b2fd4a8febb704a1fbfb92db961f641f93d4fc78122d9877e1ca6da5c8b5f),
(0x37ccc28e4680291c3df089c6fe4e0b69ecd5a560f43304c614d7dced6ee08eb1,0x4e80c89db679fae351891aa36921ab5f48b637a9de0b58cc37af904c1d5c7e07),
(0x16374bf8ab4a7a0df026b79aaeb413f6b1b3a1cc817751c8e5c7c8a00eb3d276,0x490c4b81e9e4db79f978f95958827a9d03d2dead4fdcba50815cb7ef74f37d1a),
(0x05fb64b41c47522bef7e9c7b06f98abdf67be15cad4e04546a14526e64a55ebc,0x5d6049184ad917bec99aa55dc97c8edb585e973f0d07ccfa50e46518db28275b),
(0x0d5ec71f95d3b0b7ed6155dc1c482db9e4bd97a0c7ddd8dddd72a5cf4702e49a,0x09c6eb0e7d84be6b3373d4337add32a79623898dd6a5ea57f8216bf4c6ec4882),
(0x2af93d9cb12db49561066d66aac851945562dc9e5917a7e4aea385b96a8b0100,0x78b661cb135ce2751f924f7a62a951c7c24b2f436fdc90be48fb0c4b1997dd85),
(0x2c325cee3dd9b9a68403a0be9a26d20aa057804417e3c1d7caf174f407e5be05,0x6bff133e8bdd62ad16971723b400aaa021d2fded7b79a9362e103380c28ecaff),
(0x35d770965a1dcc6b0cbd3bc3858244b5c7d249624494839bc9f9cca32b5ad096,0x08f10f3cd2d4b6fda5bb3fa097f5b608d9f2b8965b148478376b45b8af179a02),
(0x1179e35b72b63758f8c7e2647c6ca81752ea789305cf38d34422e9676f550217,0x55c7869968a944116c631dd70f5d8f892915e1ddfbae57b747afe8e257025b0d),
(0x2af1b78b30a30057c0d40ec76a8a1328983fa474bee0788156a8a202ea894868,0x694a5dfe341e94eab7026a4639bea425e90bd23a759b18c6a5310b57275c9da0),
(0x256f0a2bd740800aa7ebad9803215a8f75a3117e18a3f97a86e1a9a697471a65,0x3a08084aa98a06ce5f2d3c4d75f3a2f8f1aea4989ac54bb33abfeed8cb93be20),
(0x2283172d056278a24e11024ed27d3f9c27ad91bb3269230202e649ed08507bd2,0x57ff3e743dc4633cce8cb2365a1294082c8d1b0399360a2f6e3e1b5a47a99a9c),
(0x0f501eb466656489a2f5c1c359bc719257a2b96aa289750f9e7e8fd9592fcb79,0x098725a529e09592e80c948f98e4c24d26c2929b4dd64ecb82fb17ce6fb3e62e),
(0x155e9a1ec1efa4723b03652aae3bde573fa4f88e12ee3dce9260b5d70a34420f,0x57c790966cf4733d05907d98024f3a6edda98e4205b905a270001e9b55d1dca5),
(0x0fd200084e28fb73f308b72d1f4817c8e85402b64055fd4470d93320d3785d1a,0x761607f0fc020df5268674ca1da73bbe86a532b5d8641995aabddfff4e12ce57),
(0x2e2ef1956c0f7c0d670e2aaf746f862dd357827a1f11011fc668a65540768da1,0x68438813134e5a4a79adbef436ac4b346c27f91d77e82df89b2a6aeb4890abfa),
(0x2c8ccf4b35c3798eaa92b7baeecae9977c5f0a0185be5712ae4da969a6eedfde,0x3b1f8c06a7ef8bae09cdaef430c04be537887a89fc667bdc1a34c4fac1595148),
(0x2a7ef5d233bcf7dac30fd26cb9bf97e488f0ba67c0efe9c77fed2e93944d8ec5,0x4295b408841af3d360c848b4b453e73c1abf3eb644ee5161686db5a8909dc2a1),
(0x07a6beb071c915cf0d0ebfe70b35b0ff0bef1fe20b86f4b7d1e876d48b31acb3,0x1fca672d02dff4440676693da4a4b0297b6486753111ff3863ba45d32913ade6),
(0x0578987fe8e5d51c14adec2e1f6db305845e8c352c334db308c7d9f7d311e055,0x0917e1b0f269a7fd11db658bd0b061fb14d2a4d42e0965036046a7ddea8f71b4),
(0x0a03bde685d1a307cc534124e8105e627f338e3269dca9a47b6d28992df18eef,0x61eb41b04e2adcc2667484a34110abeebe096e45c41c8f3605ee4fa1c89ca24f),
(0x27769a082445fd9ed0395001b05e5681e6486882c10e1e267512708a046e7305,0x45907da5f53a6039c250821c0f8cdc5d3b74a080674596ad961abe45a1414241),
(0x1789c532f5787319639987f2e3d04be21ef57d9e1cd5151642e590336a1c0f9e,0x0d0a4c3011f99055ea1b2fd72ed4feb9610b3619976669a1bf0920d37c2a81c7),
(0x121f8c18143c861112f6aae5e3b67b7a80b1d5a8d0068114cce8f7743d222f78,0x5c93f690d3fbf300654279bcfa3924109a75e66965d932629162e9f0d11fc172),
(0x38fe960a91cb517d9366446ce6b038b91961cf08526a2fa3c999ec29fc4a3ba7,0x4113f20d6fbbaa11b9dcc35548d2df58da22de5141b0582f8a0f55e85b040efc),
(0x1fa7119b52433e5d81e645f132a2c908ff42c27555e0698160252d2d515a43fc,0x7dd8f143d237b554a8fcb2154bbdf445de37fb2ce4656f2369db17ed3c993a52),
(0x33daa340989ac98ff07765a7bac4db9a37fad1cd0711ee3cb04401b04d3f2284,0x33ffa6e4db20db65069e87d2be7bf28a38bbdf2f71aa5379b38cbfee2d293d6b),
(0x1ebd2835579b603aa79c38e56982f436c17ddd354c2bd03b02cc8e2be36ac5ee,0x06de6550ca5d285ae183b33a2c504b96f842f97a4c6e7c99a00f51f00b15a525),
(0x20c8ca7fcf284a0b11afe6b735d34ff8c5a4b6e30d7c73193c0359eed19474c0,0x62c5cc2ac62fd562fcb633fcac2c16c04dde3eba86005ed9f6721308f1d4c06e),
(0x10b6b313cd4bbddd943dafe69c54a97c94cddca1f55b259cf2356e0b1c8334a2,0x3e13285c9356f3435852c36e0a28efacab11440e6de04b11487e75f064ee43c8),
(0x1bb9a4c13f3b8ee114963f7540f70e5e2b057023126a512ed237779a4edf5308,0x269dfda804d7f866b0ba69c04cee25bb5e3c8b36ab93af335ce666345b7bd4c6),
(0x07c1fa5c3b6dc3e3761ab5dcbad794beeeefd74bb2358eaa4f184a179c8df0a4,0x27ff30d28901d110cf50f9deffa0d1b480b1345fec801a2dde95e7f6649b03c4),
(0x1404397546c70250c71bdd77aac118c723a9a6707f4d2937e315d62577d00913,0x7a6d3cfcc08238236a8212a6a15575be8f8c1c669a7d6f333bbf3d6cdc1c52fa),
(0x092fc5f2ffe64b2ee96fc185c9b08b6cead1d1726ab6c2fb986a71140dacce99,0x673f1b27ed4c827abb4521e17c8a9114d4a774a48b904189d0e5bff9bf29714a),
(0x39d8ae7edb0e30073a0e109892716e36add92fa0c0ce99797f55e182bee15245,0x0d624b1171bbb7f54396a3c276769f06f13a4c5ba663a50e788534a52474408f),
(0x1b9b1daaa7ea6b89f43ccc4ee456f9af174bc95ecf401349e0a4461cd1d18871,0x419f6832e80aa836f5fee537593318316aa93f83b3c3869163025d93d860bd63),
(0x1c2bb67d85d72d79c0f8d7f902d3e65b3f1220d0d896db35a73f50072a9fb61a,0x0dcf37b880e6d34b47865b30c3accd9312e18c7a138e8b68d75fb45de2cc2875),
(0x1377aa06b3dd07c58e0370706ebd0563c155a888c3d9d33d1cc9a423ba5740b9,0x6725250788de0f6fa3c8db5f0f7e6d479e86791445a8d18e611c959bddf7f3ae),
(0x2e778e955a007f2d336781bf08319397eb01b3bc922d6dd7a47d0db4cd523bfe,0x2824d9c49abb270c56dc53f99101b97d5b85d76239d226817b72709eeb5c3f16)
]
base = (0x2697d8373aeb763fdc1dbf5eefffd1b3e8d90bc1b61f92c9a5aad68079eeef2c,0x47d0e827cb1595e1470eb88580d5716c4cf22832ea2f0ff0df38ab61ca32112f)
print [eddsa_to_decaf_opt(x,y) == eddsa_to_decaf(x,y) for _,enc in points for x,y in [eddsa_decode(enc)]]
print [s == eddsa_to_decaf(*decaf_to_eddsa(s)) for s,_ in points]
print [s == eddsa_to_decaf_opt(*decaf_to_eddsa_opt(s)) for s,_ in points]